/**
 * Copyright &copy; 2012-2014 <a href="https://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
 */
package com.hw.busi.dao.domain;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

/**
 * 分页类
 * @param <T>
 * @author ThinkGem
 * @version 2013-7-2
 */
public class Page<T> implements Serializable {
   private static final long serialVersionUID = -6763373476188994592L;
   private int pageNo = 1; // 当前页码
   private int pageSize = 10; //Integer.valueOf(Global.getConfig("page.pageSize")); // 页面大小，设置为“-1”表示不进行分页（分页无效）
   
   private long count;// 总记录数，设置为“-1”表示不查询总数
   
   private int first;// 首页索引
   private int last;// 尾页索引
   private int prev;// 上一页索引
   private int next;// 下一页索引
   
   private boolean firstPage;//是否是第一页
   private boolean lastPage;//是否是最后一页
   
   private int length = 5;// 显示页面长度
   private int slider = 0;// 前后显示页面长度
   
   private List<T> list = new ArrayList<T>();
   
   private String orderBy = ""; // 标准查询有效， 实例： updatedate desc, name asc
   
   private String funcName = "page"; // 设置点击页码调用的js函数名称，默认为page，在一页有多个分页对象时使用。
   
   private String funcParam = ""; // 函数的附加参数，第三个参数值。
   
   private String message = ""; // 设置提示消息，显示在“共n条”之后
   
   public Page() {
      this.pageSize = -1;
   }
   
   /**
    * 构造方法
    *
    * @param pageNo   当前页码
    * @param pageSize 分页大小
    */
   public Page(int pageNo, int pageSize) {
      this(pageNo, pageSize, 0);
   }
   
   /**
    * 构造方法
    *
    * @param pageNo   当前页码
    * @param pageSize 分页大小
    * @param count    数据条数
    */
   public Page(int pageNo, int pageSize, long count) {
      this(pageNo, pageSize, count, new ArrayList<T>());
   }
   
   /**
    * 构造方法
    *
    * @param pageNo   当前页码
    * @param pageSize 分页大小
    * @param count    数据条数
    * @param list     本页数据对象列表
    */
   public Page(int pageNo, int pageSize, long count, List<T> list) {
      this.setCount(count);
      this.setPageNo(pageNo);
      this.pageSize = pageSize;
      this.list = list;
   }
   
   /**
    * 初始化参数
    */
   public void initialize() {
      
      //1
      this.first = 1;
      
      this.last = (int) (count / (this.pageSize < 1 ? 20 : this.pageSize) + first - 1);
      
      if (this.count % this.pageSize != 0 || this.last == 0) {
         this.last++;
      }
      
      if (this.last < this.first) {
         this.last = this.first;
      }
      
      if (this.pageNo <= 1) {
         this.pageNo = this.first;
         this.firstPage = true;
      }
      
      if (this.pageNo >= this.last) {
         this.pageNo = this.last;
         this.lastPage = true;
      }
      
      if (this.pageNo < this.last - 1) {
         this.next = this.pageNo + 1;
      } else {
         this.next = this.last;
      }
      
      if (this.pageNo > 1) {
         this.prev = this.pageNo - 1;
      } else {
         this.prev = this.first;
      }
      if (this.pageNo < this.first) {// 如果当前页小于首页
         this.pageNo = this.first;
      }
      if (this.pageNo > this.last) {// 如果当前页大于尾页
         this.pageNo = this.last;
      }
      
   }
   
   /**
    * <div class="pagination">
    * <span class="gray">&lt;</span>
    * <span class="selected">1</span>
    * <span>2</span>
    * <span>3</span>
    * <span>4</span>
    * <span>5</span>
    * <span class="page-mone">...</span>
    * <span>&gt;</span>
    * <span class="pagination-sum">
    * <span>共20页，</span>
    * <span>到第</span><input type="text" value="1">
    * <span>页</span>
    * <a href="JavaScript:void(0);" class="btn">确认</a>
    * </span>
    * </div>
    * 默认输出当前分页标签
    * <div class="page">${page}</div>
    */
   @Override
   public String toString() {
      
      StringBuilder sb = new StringBuilder();
      
      if (pageNo == first) { // 如果是首页
         sb.append("<span class=\"gray\">&lt;</span>\n");
      } else {
         sb.append("<span onclick=\"" + funcName + "(" + prev + "," + pageSize + ",'" + funcParam + "');\">&lt;</span>\n");
      }
      
      int begin = pageNo - (length / 2);
      
      if (begin < first) {
         begin = first;
      }
      
      int end = begin + length - 1;
      
      if (end >= last) {
         end = last;
         begin = end - length + 1;
         if (begin < first) {
            begin = first;
         }
      }
      
      if (begin > first) {
         int i = 0;
         for (i = first; i < first + slider && i < begin; i++) {
            sb.append("<span onclick=\"" + funcName + "(" + i + "," + pageSize + ",'" + funcParam + "');\">"
                  + (i + 1 - first) + "</span>\n");
         }
         if (i < begin) {
            sb.append("<span class=\"page-mone\">...</span>\n");
         }
      }
      
      for (int i = begin; i <= end; i++) {
         if (i == pageNo) {
            sb.append("<span class=\"selected\">" + (i + 1 - first) + "</span>\n");
         } else {
            sb.append("<span onclick=\"" + funcName + "(" + i + "," + pageSize + ",'" + funcParam + "');\">"
                  + (i + 1 - first) + "</span>\n");
         }
      }
      
      if (last - end > slider) {
         sb.append("<span class=\"page-mone\">...</span>\n");
         end = last - slider;
      }
      
      for (int i = end + 1; i <= last; i++) {
         sb.append("<span onclick=\"" + funcName + "(" + i + "," + pageSize + ",'" + funcParam + "');\">"
               + (i + 1 - first) + "</span>\n");
      }
      
      if (pageNo == last) {
         sb.append("<span>&gt;</span>\n");
      } else {
         sb.append("<span onclick=\"" + funcName + "(" + next + "," + pageSize + ",'" + funcParam + "');\">"
               + "&gt;</span>\n");
      }
      sb.append("<span class=\"pagination-sum\"> ");
      sb.append("<span>共" + last + "页，</span>");
      sb.append("<span>到第</span>");
      sb.append("<input id=\"pageGoto\" type=\"text\" value=\"" + pageNo + "\" onkeypress=\"var e=window.event||this;var c=e.keyCode||e.which;if(c==13)");
      sb.append(funcName + "(this.value," + pageSize + ",'" + funcParam + "');\" onclick=\"this.select();\"/>");
      sb.append("<span>页</span>");
      sb.append("<a href=\"javaScript:void(0);\" class=\"btn\" onclick=\"" + funcName + "($('#pageGoto').val()," + pageSize + ",'" + funcParam + "');\">跳转</a>");
      sb.append("</span>");
      StringBuffer pageSelectHtml = new StringBuffer();
      pageSelectHtml.append("<select id=\"pageSelect\" class=\"pagination-select select2-offscreen\" tabindex=\"-1\" onchange=\"page(1,this.value)\">");
      switch (pageSize) {
         case 10:
            pageSelectHtml.append("<option value=\"10\" selected='selected'>每页10条</option><option value=\"20\">每页20条</option><option value=\"30\">每页30条</option>");
            break;
         case 20:
            pageSelectHtml.append("<option value=\"10\">每页10条</option><option value=\"20\" selected='selected'>每页20条</option><option value=\"30\">每页30条</option>");
            break;
         case 30:
            pageSelectHtml.append("<option value=\"10\">每页10条</option><option value=\"20\">每页20条</option><option value=\"30\" selected='selected'>每页30条</option>");
            break;
         default:
            pageSelectHtml.append("<option value=\"10\" selected='selected'>每页10条</option><option value=\"20\">每页20条</option><option value=\"30\">每页30条</option>");
            break;
      }
      pageSelectHtml.append("</select>");
      sb.insert(0, pageSelectHtml);
      return sb.toString();
   }
   
   /**
    * 获取分页HTML代码
    *
    * @return
    */
   public String getHtml() {
      return toString();
   }
   
   /**
    * 设置每页显示的大小
    *
    * @return
    */
   public String getNewPageHtml() {
      
      StringBuilder sb = new StringBuilder();
      
      sb.append("<select onchange=\"pageSize(this);\" name=\"pageSize\" class=\"pagination-select\">\n");
      
      sb.append("<option value=\"10\" " + (this.pageSize == 10 ? "selected" : "") + ">每页10条</option>\n");
      sb.append("<option value=\"20\" " + (this.pageSize == 20 ? "selected" : "") + ">每页20条</option>\n");
      sb.append("<option value=\"30\" " + (this.pageSize == 30 ? "selected" : "") + ">每页30条</option>\n");
      sb.append("</select>");
      
      if (pageNo == first) { // 如果是首页
         sb.append("<span class=\"gray\">&lt;</span>\n");
      } else {
         sb.append("<span onclick=\"" + funcName + "(" + prev + "," + pageSize + ",'" + funcParam + "');\">&lt;</span>\n");
      }
      
      int begin = pageNo - (length / 2);// 显示的页面数 跳转的起点
      
      if (begin < first) { // 如果在首页
         begin = first;
      }
      
      int end = begin + length - 1;// 显示的页面跳转数量的终点
      
      if (end >= last) {// 如果已经到达最后一页
         end = last;
         begin = end - length + 1;
         if (begin < first) {// 总共页面数小于需要显示的跳转数（length）
            begin = first;
         }
      }
      
      if (begin > first) {// 如果起点不是首页
         int i = 0;
         for (i = first; i < first + slider && i < begin; i++) {
            sb.append("<span onclick=\"" + funcName + "(" + i + "," + pageSize + ",'" + funcParam + "');\">"
                  + (i + 1 - first) + "</span>\n");
         }
         if (i < begin) {
            sb.append("<span class=\"page-mone\">...</span>\n");
         }
      }
      
      //
      for (int i = begin; i <= end; i++) {
         if (i == pageNo) {// 在被选中的页码
            sb.append("<span class=\"selected\">" + (i + 1 - first) + "</span>\n");
         } else {
            sb.append("<span onclick=\"" + funcName + "(" + i + "," + pageSize + ",'" + funcParam + "');\">"
                  + (i + 1 - first) + "</span>\n");
         }
      }
      
      if (last - end > slider) {
         sb.append("<span class=\"page-mone\">...</span>\n");
         end = last - slider;
      }
      
      for (int i = end + 1; i <= last; i++) {
         sb.append("<span onclick=\"" + funcName + "(" + i + "," + pageSize + ",'" + funcParam + "');\">"
               + (i + 1 - first) + "</span>\n");
      }
      
      if (pageNo == last) {
         sb.append("<span>&gt;</span>\n");
      } else {
         sb.append("<span onclick=\"" + funcName + "(" + next + "," + pageSize + ",'" + funcParam + "');\">"
               + "&gt;</span>\n");
      }
      sb.append("<span class=\"pagination-sum\"> ");
      sb.append("<span>共" + last + "页，</span>");
      sb.append("<span>到第</span>");
      sb.append("<input id=\"pageGoto\" type=\"text\" value=\"" + pageNo + "\" onkeypress=\"var e=window.event||this;var c=e.keyCode||e.which;if(c==13)");
      sb.append(funcName + "(this.value," + pageSize + ",'" + funcParam + "');\" onclick=\"this.select();\"/>");
      sb.append("<span>页</span>");
      sb.append("<a href=\"javaScript:void(0);\" class=\"btn-gray-outline mgl-10\" onclick=\"" + funcName + "($('#pageGoto').val()," + pageSize + ",'" + funcParam + "');\">确认</a>");
      sb.append("</span>");
      
      
      return sb.toString();
   }

//	public static void main(String[] args) {
//		Page<String> p = new Page<String>(3, 3);
//		System.out.println(p);
//		System.out.println("首页："+p.getFirst());
//		System.out.println("尾页："+p.getLast());
//		System.out.println("上页："+p.getPrev());
//		System.out.println("下页："+p.getNext());
//	}
   
   /**
    * 获取设置总数
    *
    * @return
    */
   public long getCount() {
      return count;
   }
   
   /**
    * 设置数据总数
    *
    * @param count
    */
   public void setCount(long count) {
      this.count = count;
      if (pageSize >= count) {
         pageNo = 1;
      }
   }
   
   /**
    * 获取当前页码
    *
    * @return
    */
   public int getPageNo() {
      return pageNo;
   }
   
   /**
    * 设置当前页码
    *
    * @param pageNo
    */
   public void setPageNo(int pageNo) {
      this.pageNo = pageNo;
   }
   
   /**
    * 获取页面大小
    *
    * @return
    */
   public int getPageSize() {
      return pageSize;
   }
   
   /**
    * 设置页面大小（最大500）
    *
    * @param pageSize
    */
   public void setPageSize(int pageSize) {
      this.pageSize = pageSize <= 0 ? 10 : pageSize;// > 500 ? 500 : pageSize;
   }
   
   /**
    * 首页索引
    *
    * @return
    */
   public int getFirst() {
      return first;
   }
   
   /**
    * 尾页索引
    *
    * @return
    */
   public int getLast() {
      return last;
   }
   
   /**
    * 获取页面总数
    *
    * @return getLast();
    */
   
   public int getTotalPage() {
      return getLast();
   }
   
   /**
    * 是否为第一页
    *
    * @return
    */
   
   public boolean isFirstPage() {
      return firstPage;
   }
   
   /**
    * 是否为最后一页
    *
    * @return
    */
   
   public boolean isLastPage() {
      return lastPage;
   }
   
   /**
    * 上一页索引值
    *
    * @return
    */
   
   public int getPrev() {
      if (isFirstPage()) {
         return pageNo;
      } else {
         return pageNo - 1;
      }
   }
   
   /**
    * 下一页索引值
    *
    * @return
    */
   
   public int getNext() {
      if (isLastPage()) {
         return pageNo;
      } else {
         return pageNo + 1;
      }
   }
   
   /**
    * 获取本页数据对象列表
    *
    * @return List<T>
    */
   public List<T> getList() {
      return list;
   }
   
   /**
    * 设置本页数据对象列表
    *
    * @param list
    */
   public Page<T> setList(List<T> list) {
      this.list = list;
      initialize();
      return this;
   }
   
   /**
    * 获取查询排序字符串
    *
    * @return
    */
   
   public String getOrderBy() {
      // SQL过滤，防止注入
      String reg = "(?:')|(?:--)|(/\\*(?:.|[\\n\\r])*?\\*/)|"
            + "(\\b(select|update|and|or|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute)\\b)";
      Pattern sqlPattern = Pattern.compile(reg, Pattern.CASE_INSENSITIVE);
      if (sqlPattern.matcher(orderBy).find()) {
         return "";
      }
      return orderBy;
   }
   
   /**
    * 设置查询排序，标准查询有效， 实例： updatedate desc, name asc
    */
   public void setOrderBy(String orderBy) {
      this.orderBy = orderBy;
   }
   
   /**
    * 获取点击页码调用的js函数名称
    * function ${page.funcName}(pageNo){location="${ctx}/list-${category.id}${urlSuffix}?pageNo="+i;}
    *
    * @return
    */
   
   public String getFuncName() {
      return funcName;
   }
   
   /**
    * 设置点击页码调用的js函数名称，默认为page，在一页有多个分页对象时使用。
    *
    * @param funcName 默认为page
    */
   public void setFuncName(String funcName) {
      this.funcName = funcName;
   }
   
   /**
    * 获取分页函数的附加参数
    *
    * @return
    */
   
   public String getFuncParam() {
      return funcParam;
   }
   
   /**
    * 设置分页函数的附加参数
    *
    * @return
    */
   public void setFuncParam(String funcParam) {
      this.funcParam = funcParam;
   }
   
   /**
    * 设置提示消息，显示在“共n条”之后
    *
    * @param message
    */
   public void setMessage(String message) {
      this.message = message;
   }
   
   /**
    * 分页是否有效
    *
    * @return this.pageSize==-1
    */
   
   public boolean isDisabled() {
      return this.pageSize == -1;
   }
   
   /**
    * 是否进行总数统计
    *
    * @return this.count==-1
    */
   
   public boolean isNotCount() {
      return this.count == -1;
   }
   
   /**
    * 获取 Hibernate FirstResult
    */
   public int getFirstResult() {
      int firstResult = (getPageNo() - 1) * getPageSize();
      if (firstResult >= getCount()) {
         firstResult = 0;
      }
      return firstResult;
   }
   
   /**
    * 获取 Hibernate MaxResults
    */
   public int getMaxResults() {
      return getPageSize();
   }
}
